package cn.demo.common.utils;

import cn.demo.common.constant.CommonConstants;
import cn.demo.common.core.text.StrFormatter;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 字符串工具类
 *
 * @author ruoyi
 */
public class StringUtils extends org.springframework.util.StringUtils {
    /**
     * null字符串
     */
    public static final String NULLSTR = "null";

    /**
     * 空字符串
     */
    public static final String EMPTY = "";

    /**
     * 空格字符串
     */
    public static final String SPACE = " ";

    /**
     * LF换行符
     */
    public static final String LF = "\n";

    /**
     * CR换行符
     */
    public static final String CR = "\r";

    /**
     * 下划线
     */
    public static final char UNDERLINE = '_';

    /**
     * 分隔符
     */
    public static final String DELIMITER = ",";

    /**
     * 星号
     */
    public static final char ASTERISK = '*';

    /**
     * 索引搜索失败
     */
    public static final int INDEX_NOT_FOUND = -1;

    /**
     * 填充常数可扩展的最大尺寸
     */
    private static final int PAD_LIMIT = 8192;

    /**
     * 获取参数不为空值
     *
     * @param value        要判断的value
     * @param defaultValue 返回的默认值
     * @return value 返回值
     */
    public static <T extends CharSequence> T nvl(final T value, final T defaultValue) {
        return value != null ? value : defaultValue;
    }

    /**
     * 获取参数不为空白字符串值
     *
     * @param str        字符串
     * @param defaultStr 返回的默认值
     * @param <T>        字符串的具体类型
     * @return
     */
    public static <T extends CharSequence> T defaultIfBlank(final T str, final T defaultStr) {
        return isBlank(str) ? defaultStr : str;
    }

    /**
     * 获取参数不为空串值
     *
     * @param str        字符串
     * @param defaultStr 返回的默认值
     * @param <T>        字符串的具体类型
     * @return
     */
    public static <T extends CharSequence> T defaultIfEmpty(final T str, final T defaultStr) {
        return isEmpty(str) ? defaultStr : str;
    }

    /**
     * 判断字符串是为空白字符串
     *
     * @param cs 字符串
     * @return 返回值
     */
    public static boolean isBlank(final CharSequence cs) {
        final int strLen = length(cs);
        if (strLen == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if (!Character.isWhitespace(cs.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断字符串不是空白字符串
     *
     * @param cs 字符串
     * @return 返回值
     */
    public static boolean isNotBlank(final CharSequence cs) {
        return !isBlank(cs);
    }

    /**
     * 获取字符串长度
     *
     * @param cs 字符串
     * @return 长度
     */
    public static int length(final CharSequence cs) {
        return cs == null ? 0 : cs.length();
    }

    /**
     * * 判断一个字符串是否为空串
     *
     * @param str String
     * @return true：为空 false：非空
     */
    public static boolean isEmpty(CharSequence str) {
        return ObjectUtils.isEmpty(str);
    }


    /**
     * * 判断一个字符串是否为非空串
     *
     * @param str String
     * @return true：非空串 false：空串
     */
    public static boolean isNotEmpty(String str) {
        return !isEmpty(str);
    }

    /**
     * 去空格
     */
    public static String trim(String str) {
        return (str == null ? EMPTY : str.trim());
    }

    /**
     * 替换指定字符串的指定区间内字符为"*"
     *
     * @param str          字符串
     * @param startInclude 开始位置（包含）
     * @param endExclude   结束位置（不包含）
     * @return 替换后的字符串
     */
    public static String hide(CharSequence str, int startInclude, int endExclude) {
        if (isEmpty(str)) {
            return EMPTY;
        }
        final int strLength = str.length();
        if (startInclude > strLength) {
            return EMPTY;
        }
        if (endExclude > strLength) {
            endExclude = strLength;
        }
        if (startInclude > endExclude) {
            // 如果起始位置大于结束位置，不替换
            return EMPTY;
        }
        final char[] chars = new char[strLength];
        for (int i = 0; i < strLength; i++) {
            if (i >= startInclude && i < endExclude) {
                chars[i] = ASTERISK;
            } else {
                chars[i] = str.charAt(i);
            }
        }
        return new String(chars);
    }

    /**
     * 截取字符串
     *
     * @param str   字符串
     * @param start 开始
     * @return 结果
     */
    public static String substring(final String str, int start) {
        if (str == null) {
            return EMPTY;
        }

        if (start < 0) {
            start = str.length() + start;
        }

        if (start < 0) {
            start = 0;
        }
        if (start > str.length()) {
            return EMPTY;
        }

        return str.substring(start);
    }

    /**
     * 截取字符串
     *
     * @param str   字符串
     * @param start 开始
     * @param end   结束
     * @return 结果
     */
    public static String substring(final String str, int start, int end) {
        if (str == null) {
            return EMPTY;
        }

        if (end < 0) {
            end = str.length() + end;
        }
        if (start < 0) {
            start = str.length() + start;
        }

        if (end > str.length()) {
            end = str.length();
        }

        if (start > end) {
            return EMPTY;
        }

        if (start < 0) {
            start = 0;
        }
        if (end < 0) {
            end = 0;
        }

        return str.substring(start, end);
    }

    /**
     * 判断是否为空，并且不是空白字符
     *
     * @param str 要判断的value
     * @return 结果
     */
    public static boolean hasText(String str) {
        return (str != null && !str.isEmpty() && containsText(str));
    }

    private static boolean containsText(CharSequence str) {
        int strLen = str.length();
        for (int i = 0; i < strLen; i++) {
            if (!Character.isWhitespace(str.charAt(i))) {
                return true;
            }
        }
        return false;
    }

    /**
     * 格式化文本, {} 表示占位符<br>
     * 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
     * 如果想输出 {} 使用 \\转义 { 即可，如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
     * 例：<br>
     * 通常使用：format("this is {} for {}", "a", "b") -> this is a for b<br>
     * 转义{}： format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
     * 转义\： format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
     *
     * @param template 文本模板，被替换的部分用 {} 表示
     * @param params   参数值
     * @return 格式化后的文本
     */
    public static String format(String template, Object... params) {
        if (isEmpty(params) || isEmpty(template)) {
            return template;
        }
        return StrFormatter.format(template, params);
    }

    /**
     * 是否为http(s)://开头
     *
     * @param link 链接
     * @return 结果
     */
    public static boolean ishttp(String link) {
        return StringUtils.startsWithAny(link, CommonConstants.HTTP, CommonConstants.HTTPS);
    }

    /**
     * 是否字符串开头
     *
     * @param str        字符串
     * @param prefix     要查找的前缀
     * @param ignoreCase 是否忽略大小写
     * @return 结果
     */
    private static boolean startsWith(String str, String prefix, final boolean ignoreCase) {
        if (str == null || prefix == null) {
            return str == prefix;
        }
        final int preLen = prefix.length();
        if (preLen > str.length()) {
            return false;
        }
        if (ignoreCase) {
            return str.toLowerCase().startsWith(prefix.toLowerCase());
        } else {
            return str.startsWith(prefix);
        }
    }

    /**
     * 是否字符串开头
     *
     * @param str    字符串
     * @param prefix 要查找的前缀
     * @return 结果
     */
    public static boolean startsWith(String str, String prefix) {
        return startsWith(str, prefix, false);
    }

    /**
     * 是否字符串开头-忽略大小写
     *
     * @param str    字符串
     * @param prefix 要查找的前缀
     * @return 结果
     */
    public static boolean startsWithIgnoreCase(String str, String prefix) {
        return startsWith(str, prefix, true);
    }

    /**
     * @param str        字符串
     * @param ignoreCase 是否忽略大小写
     * @param prefixs    匹配的字符串
     * @return 结果
     */
    private static boolean startsWithAny(String str, boolean ignoreCase, String... prefixs) {
        if (!isEmpty(str) && ArrayUtils.isNotEmpty(prefixs)) {
            for (String prefix : prefixs) {
                if ((ignoreCase && startsWithIgnoreCase(str, prefix) || (!ignoreCase && startsWith(str, prefix)))) {
                    return true;
                }
            }
        } else {
            return false;
        }
        return false;
    }

    /**
     * 是否为其中一个开头
     *
     * @param str     字符串
     * @param prefixs 匹配的字符串
     * @return 结果
     */
    public static boolean startsWithAny(String str, String... prefixs) {
        return startsWithAny(str, false, prefixs);
    }

    /**
     * 是否为其中一个开头-忽略大小写
     *
     * @param str     字符串
     * @param prefixs 匹配的字符串
     * @return 结果
     */
    public static boolean startsWithAnyIgnoreCase(String str, String... prefixs) {
        return startsWithAny(str, true, prefixs);
    }

    /**
     * 是否字符串结尾
     *
     * @param str    字符串
     * @param suffix 要查找的后缀
     * @return 结果
     */
    public static boolean endsWith(final String str, final String suffix) {
        return endsWith(str, suffix, false);
    }

    /**
     * 是否字符串结尾-忽略大小写
     *
     * @param str    字符串
     * @param suffix 要查找的后缀
     * @return 结果
     */
    public static boolean endsWithIgnoreCase(final String str, final String suffix) {
        return endsWith(str, suffix, true);
    }

    /**
     * 是否字符串结尾
     *
     * @param str        字符串
     * @param suffix     要查找的后缀
     * @param ignoreCase 是否忽略大小写
     * @return 结果
     */
    private static boolean endsWith(final String str, final String suffix, final boolean ignoreCase) {
        if (str == null || suffix == null) {
            return str == suffix;
        }
        if (suffix.length() > str.length()) {
            return false;
        }
        final int strOffset = str.length() - suffix.length();
        if (ignoreCase) {
            return str.toLowerCase().endsWith(suffix.toLowerCase());
        } else {
            return str.endsWith(suffix);
        }
    }

    /**
     * 字符串转set
     *
     * @param str 字符串
     * @param sep 分隔符
     * @return set集合
     */
    public static final Set<String> str2Set(String str, String sep) {
        return new HashSet<String>(str2List(str, sep, true, false));
    }

    /**
     * 字符串转list
     *
     * @param str         字符串
     * @param sep         分隔符
     * @param filterBlank 过滤纯空白
     * @param trim        去掉首尾空白
     * @return list集合
     */
    public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim) {
        List<String> list = new ArrayList<String>();
        if (StringUtils.isEmpty(str)) {
            return list;
        }

        // 过滤空白字符串
        if (filterBlank && StringUtils.isBlank(str)) {
            return list;
        }
        String[] split = str.split(sep);
        for (String string : split) {
            if (filterBlank && StringUtils.isBlank(string)) {
                continue;
            }
            if (trim) {
                string = string.trim();
            }
            list.add(string);
        }

        return list;
    }

    /**
     * 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
     *
     * @param cs                  指定字符串
     * @param ignoreCase          是否忽略大小写
     * @param searchCharSequences 需要检查的字符串数组
     * @return 是否包含任意一个字符串
     */
    private static boolean containsAny(CharSequence cs, boolean ignoreCase, CharSequence... searchCharSequences) {
        if (ObjUtils.isEmpty(cs) || ObjUtils.isEmpty(searchCharSequences)) {
            return false;
        }
        for (CharSequence testStr : searchCharSequences) {
            if ((ignoreCase && containsIgnoreCase(cs, testStr)) || (!ignoreCase && contains(cs, testStr))) {
                return true;
            }
        }
        return false;
    }

    /**
     * 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
     *
     * @param cs                  指定字符串
     * @param searchCharSequences 需要检查的字符串数组
     * @return 是否包含任意一个字符串
     */
    public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) {
        return containsAny(cs, true, searchCharSequences);

    }

    /**
     * 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
     *
     * @param cs                  指定字符串
     * @param searchCharSequences 需要检查的字符串数组
     * @return 是否包含任意一个字符串
     */
    public static boolean containsAny(CharSequence cs, CharSequence... searchCharSequences) {
        return containsAny(cs, false, searchCharSequences);
    }

    /**
     * 是否包含字符串
     *
     * @param cs         字符串
     * @param testStr    要查找的字符串
     * @param ignoreCase 是否忽略大小写
     * @return 返回值
     */
    private static boolean contains(CharSequence cs, CharSequence testStr, boolean ignoreCase) {
        if (null == cs || null == testStr) {
            return cs == testStr;
        }
        if (ignoreCase) {
            return cs.toString().toLowerCase().contains(testStr.toString().toLowerCase());
        } else {
            return cs.toString().contains(testStr);
        }
    }

    /**
     * 是否包含字符串
     *
     * @param cs      字符串
     * @param testStr 要查找的字符串
     * @return 返回值
     */
    public static boolean contains(CharSequence cs, CharSequence testStr) {
        return contains(cs, testStr, false);
    }

    /**
     * 是否包含字符串-忽略大小写
     *
     * @param cs      字符串
     * @param testStr 要查找的字符串
     * @return 返回值
     */
    public static boolean containsIgnoreCase(CharSequence cs, CharSequence testStr) {
        return contains(cs, testStr, true);
    }


    /**
     * 判断给定的collection列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value
     *
     * @param collection 给定的集合
     * @param array      给定的数组
     * @return boolean 结果
     */
    public static boolean containsAny(Collection<String> collection, String... array) {
        if (ObjUtils.isEmpty(collection) || ObjUtils.isEmpty(array)) {
            return false;
        } else {
            for (String str : array) {
                if (collection.contains(str)) {
                    return true;
                }
            }
            return false;
        }
    }

    /**
     * 驼峰转下划线命名
     */
    public static String toUnderScoreCase(String str) {
        if (str == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        // 前置字符是否大写
        boolean preCharIsUpperCase = true;
        // 当前字符是否大写
        boolean curreCharIsUpperCase = true;
        // 下一字符是否大写
        boolean nexteCharIsUpperCase = true;
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if (i > 0) {
                preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
            } else {
                preCharIsUpperCase = false;
            }

            curreCharIsUpperCase = Character.isUpperCase(c);

            if (i < (str.length() - 1)) {
                nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
            }

            if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) {
                sb.append(UNDERLINE);
            } else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) {
                sb.append(UNDERLINE);
            }
            sb.append(Character.toLowerCase(c));
        }

        return sb.toString();
    }

    /**
     * 是否包含字符串
     *
     * @param str  验证字符串
     * @param strs 字符串组
     * @return 包含返回true
     */
    public static boolean inStringIgnoreCase(String str, String... strs) {
        if (str != null && strs != null) {
            for (String s : strs) {
                if (str.equalsIgnoreCase(trim(s))) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空，则返回空字符串。 例如：HELLO_WORLD->HelloWorld
     *
     * @param name 转换前的下划线大写方式命名的字符串
     * @return 转换后的驼峰式命名的字符串
     */
    public static String toCamelCaseUp(String name) {
        StringBuilder result = new StringBuilder();
        // 快速检查
        if (name == null || name.isEmpty()) {
            // 没必要转换
            return "";
        } else if (!name.contains("_")) {
            // 不含下划线，仅将首字母大写
            return name.substring(0, 1).toUpperCase() + name.substring(1);
        }
        // 用下划线将原始字符串分割
        String[] camels = name.split("_");
        for (String camel : camels) {
            // 跳过原始字符串中开头、结尾的下换线或双重下划线
            if (camel.isEmpty()) {
                continue;
            }
            // 首字母大写
            result.append(camel.substring(0, 1).toUpperCase());
            result.append(camel.substring(1).toLowerCase());
        }
        return result.toString();
    }

    /**
     * 驼峰式命名法
     * 例如：user_name->userName
     */
    public static String toCamelCase(String s) {
        if (s == null) {
            return null;
        }
        if (s.indexOf(UNDERLINE) == -1) {
            return s;
        }
        s = s.toLowerCase();
        StringBuilder sb = new StringBuilder(s.length());
        boolean upperCase = false;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);

            if (c == UNDERLINE) {
                upperCase = true;
            } else if (upperCase) {
                sb.append(Character.toUpperCase(c));
                upperCase = false;
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * 反驼峰式命名法
     * 例如：userName->user_name
     */
    public static String fromCamelCase(String s) {
        if (s == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (Character.isUpperCase(c)) {
                sb.append('_').append(Character.toLowerCase(c));
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
     *
     * @param str  指定字符串
     * @param strs 需要检查的字符串数组
     * @return 是否匹配
     */
    public static boolean matches(String str, List<String> strs) {
        if (isEmpty(str) || isEmpty(strs)) {
            return false;
        }
        for (String pattern : strs) {
            if (isMatch(pattern, str)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断url是否与规则配置:
     * ? 表示单个字符;
     * * 表示一层路径内的任意字符串，不可跨层级;
     * ** 表示任意层路径;
     *
     * @param pattern 匹配规则
     * @param url     需要匹配的url
     * @return
     */
    public static boolean isMatch(String pattern, String url) {
        AntPathMatcher matcher = new AntPathMatcher();
        return matcher.match(pattern, url);
    }

    @SuppressWarnings("unchecked")
    public static <T> T cast(Object obj) {
        return (T) obj;
    }

    /**
     * 数字左边补齐0，使之达到指定长度。注意，如果数字转换为字符串后，长度大于size，则只保留 最后size个字符。
     *
     * @param num  数字对象
     * @param size 字符串指定长度
     * @return 返回数字的字符串格式，该字符串为指定长度。
     */
    public static final String padl(final Number num, final int size) {
        return padl(num.toString(), size, '0');
    }

    /**
     * 字符串左补齐。如果原始字符串s长度大于size，则只保留最后size个字符。
     *
     * @param s    原始字符串
     * @param size 字符串指定长度
     * @param c    用于补齐的字符
     * @return 返回指定长度的字符串，由原字符串左补齐或截取得到。
     */
    public static final String padl(final String s, final int size, final char c) {
        final StringBuilder sb = new StringBuilder(size);
        if (s != null) {
            final int len = s.length();
            if (s.length() <= size) {
                for (int i = size - len; i > 0; i--) {
                    sb.append(c);
                }
                sb.append(s);
            } else {
                return s.substring(len - size, len);
            }
        } else {
            for (int i = size; i > 0; i--) {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * 删除字符串首尾的空白
     *
     * @param str 字符串
     * @return 返回值
     */
    public static String strip(final String str) {
        return strip(str, null);
    }

    /**
     * 删除字符串首尾的特定字符串
     *
     * @param str        字符串
     * @param stripChars 要删除的字符串
     * @return
     */
    public static String strip(String str, final String stripChars) {
        str = stripStart(str, stripChars);
        return stripEnd(str, stripChars);
    }

    /**
     * 删除字符串首的特定字符串
     *
     * @param str        字符串
     * @param stripChars 要删除的字符串
     * @return
     */
    public static String stripStart(final String str, final String stripChars) {
        final int strLen = length(str);
        if (strLen == 0) {
            return str;
        }
        int start = 0;
        if (stripChars == null) {
            while (start != strLen && Character.isWhitespace(str.charAt(start))) {
                start++;
            }
        } else if (stripChars.isEmpty()) {
            return str;
        } else {
            while (start != strLen && stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND) {
                start++;
            }
        }
        return str.substring(start);
    }

    /**
     * 删除字符串尾的特定字符串
     *
     * @param str        字符串
     * @param stripChars 要删除的字符串
     * @return
     */
    public static String stripEnd(final String str, final String stripChars) {
        int end = length(str);
        if (end == 0) {
            return str;
        }

        if (stripChars == null) {
            while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) {
                end--;
            }
        } else if (stripChars.isEmpty()) {
            return str;
        } else {
            while (end != 0 && stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND) {
                end--;
            }
        }
        return str.substring(0, end);
    }


    /**
     * 获取首次出现分隔符之前的子串。不返回分隔符
     *
     * @param str       字符串
     * @param separator 分隔符
     * @return 字串
     */
    public static String substringBefore(final String str, final int separator) {
        if (isEmpty(str)) {
            return str;
        }
        final int pos = str.indexOf(separator);
        if (pos == INDEX_NOT_FOUND) {
            return str;
        }
        return str.substring(0, pos);
    }

    /**
     * 获取首次出现分隔符之前的子串。不返回分隔符
     *
     * @param str       字符串
     * @param separator 分隔符
     * @return 字串
     */
    public static String substringBefore(final String str, final String separator) {
        if (isEmpty(str) || separator == null) {
            return str;
        }
        if (separator.isEmpty()) {
            return EMPTY;
        }
        final int pos = str.indexOf(separator);
        if (pos == INDEX_NOT_FOUND) {
            return str;
        }
        return str.substring(0, pos);
    }

    /**
     * 检查 字符串 是否只包含 Unicode 数字。
     *
     * @param cs 字符串
     * @return 结果
     */
    public static boolean isNumeric(final CharSequence cs) {
        if (isEmpty(cs)) {
            return false;
        }
        final int sz = cs.length();
        for (int i = 0; i < sz; i++) {
            if (!Character.isDigit(cs.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 比较两个字符串是否相等
     *
     * @param cs1 字符串1
     * @param cs2 字符串2
     * @return 结果
     */
    public static boolean equals(final CharSequence cs1, final CharSequence cs2) {
        if (cs1 == cs2) {
            return true;
        }
        if (cs1 == null || cs2 == null) {
            return false;
        }
        if (cs1.length() != cs2.length()) {
            return false;
        }
        if (cs1 instanceof String && cs2 instanceof String) {
            return cs1.equals(cs2);
        }
        // Step-wise comparison
        final int length = cs1.length();
        for (int i = 0; i < length; i++) {
            if (cs1.charAt(i) != cs2.charAt(i)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 比较两个字符串是否相等 忽略大小写
     *
     * @param cs1 字符串1
     * @param cs2 字符串2
     * @return 结果
     */
    public static boolean equalsIgnoreCase(final CharSequence cs1, final CharSequence cs2) {
        if (cs1 == cs2) {
            return true;
        }
        if (cs1 == null || cs2 == null) {
            return false;
        }
        if (cs1.length() != cs2.length()) {
            return false;
        }
        if (cs1 instanceof String && cs2 instanceof String) {
            return ((String) cs1).equalsIgnoreCase((String) cs2);
        }
        // Step-wise comparison
        final int length = cs1.length();
        for (int i = 0; i < length; i++) {
            if (Character.toLowerCase(cs1.charAt(i)) != Character.toLowerCase(cs2.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 任意一个字符串是否与给定字符串相等
     *
     * @param string 给定字符串
     * @param searchStrings 搜索字符串数组
     * @return 结果
     */
    public static boolean equalsAny(final CharSequence string, final CharSequence... searchStrings) {
        if (ArrayUtils.isNotEmpty(searchStrings)) {
            for (final CharSequence next : searchStrings) {
                if (equals(string, next)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 任意一个字符串是否与给定字符串相等-忽略大小写
     *
     * @param string 给定字符串
     * @param searchStrings 搜索字符串数组
     * @return 结果
     */
    public static boolean equalsAnyIgnoreCase(final CharSequence string, final CharSequence...searchStrings) {
        if (ArrayUtils.isNotEmpty(searchStrings)) {
            for (final CharSequence next : searchStrings) {
                if (equalsIgnoreCase(string, next)) {
                    return true;
                }
            }
        }
        return false;
    }
    /**
     * 数组中的元素合并为一个字符串
     *
     * @param array 数组
     * @return 结果
     */
    public static String join(final Object[] array) {
        return join(Arrays.asList(array), DELIMITER);
    }

    /**
     * 数组中的元素合并为一个字符串
     *
     * @param array     数组
     * @param delimiter 分隔符
     * @return 结果
     */
    public static String join(final Object[] array, final CharSequence delimiter) {
        return join(Arrays.asList(array), delimiter);
    }

    /**
     * 列表中的元素合并为一个字符串
     *
     * @param array 数组
     * @return 结果
     */
    public static <T> String join(final Collection<T> array) {
        if (array == null) {
            return null;
        }
        return join(array, DELIMITER);
    }

    /**
     * 列表中的元素合并为一个字符串
     *
     * @param array     数组
     * @param delimiter 分隔符
     * @return 结果
     */
    public static <T> String join(final Collection<T> array, final CharSequence delimiter) {
        if (null != array) {
            return array.stream().map(Object::toString).collect(Collectors.joining(delimiter));
        }

        return null;
    }

    /**
     * 查询字符串下标
     *
     * @param seq       字符串
     * @param searchSeq 搜索字符串
     * @return 结果
     */
    public static int indexOf(final String seq, final String searchSeq) {
        if (isEmpty(seq) || isEmpty(searchSeq)) {
            return INDEX_NOT_FOUND;
        }
        return seq.indexOf(searchSeq);
    }

    public static int indexOfIgnoreCase(final String seq, final String searchSeq) {
        if (isEmpty(seq) || isEmpty(searchSeq)) {
            return INDEX_NOT_FOUND;
        }
        return indexOf(seq.toLowerCase(), searchSeq.toLowerCase());
    }

    /**
     * 获取两个字符串中间的子字符串
     *
     * @param str   字符串
     * @param open  开头字符串
     * @param close 结尾字符串
     * @return 子字符串
     */
    public static String substringBetween(final String str, final String open, final String close) {
        if (!ObjUtils.allNotNull(str, open, close)) {
            return null;
        }
        final int start = str.indexOf(open);
        if (start != INDEX_NOT_FOUND) {
            final int end = str.indexOf(close, start + open.length());
            if (end != INDEX_NOT_FOUND) {
                return str.substring(start + open.length(), end);
            }
        }
        return null;
    }

    public static String repeat(final char ch, final int repeat) {
        if (repeat <= 0) {
            return EMPTY;
        }
        final char[] buf = new char[repeat];
        Arrays.fill(buf, ch);
        return new String(buf);
    }

    /**
     * 重复字符串
     *
     * @param str    字符串
     * @param repeat 重复次数
     * @return 结果
     */
    public static String repeat(final String str, final int repeat) {
        if (str == null) {
            return null;
        }
        if (repeat <= 0) {
            return EMPTY;
        }
        final int inputLength = str.length();
        if (repeat == 1 || inputLength == 0) {
            return str;
        }
        if (inputLength == 1 && repeat <= PAD_LIMIT) {
            return repeat(str.charAt(0), repeat);
        }

        final int outputLength = inputLength * repeat;
        switch (inputLength) {
            case 1:
                return repeat(str.charAt(0), repeat);
            case 2:
                final char ch0 = str.charAt(0);
                final char ch1 = str.charAt(1);
                final char[] output2 = new char[outputLength];
                for (int i = repeat * 2 - 2; i >= 0; i--, i--) {
                    output2[i] = ch0;
                    output2[i + 1] = ch1;
                }
                return new String(output2);
            default:
                final StringBuilder buf = new StringBuilder(outputLength);
                for (int i = 0; i < repeat; i++) {
                    buf.append(str);
                }
                return buf.toString();
        }
    }

    /**
     * 重复字符串
     *
     * @param str       字符串
     * @param separator 分隔符
     * @param repeat    重复次数
     * @return 结果
     */
    public static String repeat(final String str, final String separator, final int repeat) {
        if (str == null || separator == null) {
            return repeat(str, repeat);
        }
        final String result = repeat(str + separator, repeat);
        return removeEnd(result, separator);
    }

    /**
     * 删除开头的字符串
     *
     * @param str    字符串
     * @param remove 删除的字符
     * @return 结果
     */
    public static String removeStart(final String str, final String remove) {
        if (isEmpty(str) || isEmpty(remove)) {
            return str;
        }
        if (str.startsWith(remove)) {
            return str.substring(remove.length());
        }
        return str;
    }

    /**
     * 删除末尾的字符串
     *
     * @param str    字符串
     * @param remove 删除的字符
     * @return 结果
     */
    public static String removeEnd(final String str, final String remove) {
        if (isEmpty(str) || isEmpty(remove)) {
            return str;
        }
        if (str.endsWith(remove)) {
            return str.substring(0, str.length() - remove.length());
        }
        return str;
    }

    /**
     * 获取第一次出现分隔符后的子串，分隔符不会返回
     *
     * @param str       字符串
     * @param separator 删除的字符
     * @return 结果
     */
    public static String substringAfter(final String str, final String separator) {
        if (isEmpty(str)) {
            return str;
        }
        if (separator == null) {
            return EMPTY;
        }
        final int pos = str.indexOf(separator);
        if (pos == INDEX_NOT_FOUND) {
            return EMPTY;
        }
        return str.substring(pos + separator.length());
    }

    /**
     * 批量替换
     *
     * @param text            字符串
     * @param searchList      要替换的字符
     * @param replacementList 目标字符
     * @return
     */
    public static String replaceEach(String text, final String[] searchList, final String[] replacementList) {
        if (isEmpty(text) || ArrayUtils.isEmpty(searchList) || ArrayUtils.isEmpty(replacementList)) {
            return text;
        }
        if (searchList.length != replacementList.length) {
            return text;
        }
        for (int i = 0; i < searchList.length; i++) {
            text = text.replaceFirst(searchList[i], replacementList[i]);
        }
        return text;
    }

    /**
     * 计算子字符串在给定字符串中出现的次数
     *
     * @param str    字符串
     * @param subStr 子字符串
     * @return 结果
     */
    public static int countMatches(final String str, final String subStr) {
        int count = 0;
        int index = 0;
        while ((index = str.indexOf(subStr, index)) != -1) {
            count++;
            index += subStr.length();
        }
        return count;
    }

    /**
     * 获取最后一次出现分隔符之前的子字符串。不返回分隔符。
     *
     * @param str       字符串
     * @param separator 分隔符
     * @return 结果
     */
    public static String substringBeforeLast(final String str, final String separator) {
        if (isEmpty(str) || isEmpty(separator)) {
            return str;
        }
        final int pos = str.lastIndexOf(separator);
        if (pos == INDEX_NOT_FOUND) {
            return str;
        }
        return str.substring(0, pos);
    }

    /**
     * 获取最后一次出现分隔符之后的子字符串。
     *
     * @param str       字符串
     * @param separator 分隔符
     * @return 结果
     */
    public static String substringAfterLast(final String str, final String separator) {
        if (isEmpty(str)) {
            return str;
        }
        if (isEmpty(separator)) {
            return EMPTY;
        }
        final int pos = str.lastIndexOf(separator);
        if (pos == INDEX_NOT_FOUND || pos == str.length() - separator.length()) {
            return EMPTY;
        }
        return str.substring(pos + separator.length());
    }

    /**
     * 分割字符串
     * @param toSplit 需要分割的字符串
     * @param delimiter 分割字符
     * @return 分割的结果
     */
    public static String[] split(String toSplit, String delimiter) {
        if (isEmpty(toSplit) || isEmpty(delimiter)) {
            return null;
        }
        return toSplit.split(delimiter);
    }

    /**
     *
     * 转换类名
     * @param fullClassName
     * @return
     */
    public static String convertClassName(String fullClassName) {
        // 使用正则表达式分割类名，保留点号
        String[] parts = fullClassName.split("\\.");

        // 使用StringBuilder来构建新的类名格式
        StringBuilder convertedName = new StringBuilder();

        // 遍历类名的每个部分（包名和类名）
        for (String part : parts) {
            // 如果不是最后一个部分，则只取一位，添加点号
            if (!part.equals(parts[parts.length - 1])) {
                // 只取每个部分的第一个字符，并将其转换为小写（如果需要）
                convertedName.append(part.charAt(0));
                convertedName.append(".");
            }else {
                convertedName.append(part);
            }
        }

        return convertedName.toString();
    }
}